package com.timmy.blekit.utils;

import android.app.Application;
import android.text.TextUtils;
import android.util.Log;

import com.inuker.bluetooth.library.BluetoothClient;
import com.inuker.bluetooth.library.Code;
import com.inuker.bluetooth.library.connect.options.BleConnectOptions;
import com.inuker.bluetooth.library.connect.response.BleConnectResponse;
import com.inuker.bluetooth.library.connect.response.BleNotifyResponse;
import com.inuker.bluetooth.library.connect.response.BleWriteResponse;
import com.inuker.bluetooth.library.model.BleGattProfile;
import com.inuker.bluetooth.library.search.SearchRequest;
import com.inuker.bluetooth.library.search.SearchResult;
import com.inuker.bluetooth.library.search.response.SearchResponse;
import com.timmy.blekit.callback.BleConnectCallback;
import com.timmy.blekit.callback.BleScanCallback;

import java.util.UUID;

import static com.inuker.bluetooth.library.utils.ByteUtils.isEmpty;

/**
 * @Auther: Timmy
 * @Data: 2017/8/22
 * @Fuction: 蓝牙工具类
 */

public class BleUtil {

    private static final String TAG = BleUtil.class.getSimpleName();
    private Application mContext;
    private BluetoothClient mClient;
    private String mDeviceMAC;

    public static BleUtil getInstance() {
        return BleUtilHolder.holder;
    }

    public static class BleUtilHolder {
        private static BleUtil holder = new BleUtil();
    }

    public BleUtil init(Application app) {
        mContext = app;
        mClient = new BluetoothClient(app);
        return this;
    }

    /**
     * 判断是否支持ble蓝牙
     */
    public boolean isBleSupported() {
        return mClient.isBleSupported();
    }

    /**
     * 判断蓝牙是否开启
     */
    public boolean isBluetoothOpened() {
        return mClient.isBluetoothOpened();
    }

    /**
     * 搜索蓝牙设备
     */
    public void scanBleDevice(final BleScanCallback callback) {
        SearchRequest request = new SearchRequest.Builder()
                .searchBluetoothLeDevice(3000, 3)   // 先扫BLE设备3次，每次3s
                // .searchBluetoothClassicDevice(5000) // 再扫经典蓝牙5s
                .searchBluetoothLeDevice(1000)      // 再扫BLE设备1s
                .build();


        mClient.search(request, new SearchResponse() {
            @Override
            public void onSearchStarted() {
                // 开始扫描
                callback.bleScanStart();
            }

            @Override
            public void onDeviceFounded(SearchResult device) {
                // Beacon beacon = new Beacon(device.scanRecord);
                // BluetoothLog.v(String.format("beacon for %s\n%s", device.getAddress(), beacon.toString()));

                if (!TextUtils.isEmpty(device.getName())) {
                    callback.bleDevice(device);
                }
            }

            @Override
            public void onSearchStopped() {
                // 扫描停止
                callback.bleScanStop();
            }

            @Override
            public void onSearchCanceled() {
                // 扫描取消
                callback.bleScanStop();

            }
        });
    }

    /**
     * 连接设备
     */
    public void connectDevice(String deviceMAC, final BleConnectCallback callback) {
        mDeviceMAC = deviceMAC;

        BleConnectOptions options = new BleConnectOptions.Builder()
                .setConnectRetry(3)   // 连接如果失败重试3次
                .setConnectTimeout(30000)   // 连接超时30s
                .setServiceDiscoverRetry(3)  // 发现服务如果失败重试3次
                .setServiceDiscoverTimeout(20000)  // 发现服务超时20s
                .build();

        mClient.connect(deviceMAC, options, new BleConnectResponse() {
            @Override
            public void onResponse(int code, BleGattProfile data) {
                if (code == Code.REQUEST_SUCCESS) {
                    callback.bleConnectSucc();

                    // 连接成功,开启通知
                    openNotify();


                } else if (code == Code.REQUEST_FAILED) {
                    callback.bleConnectFaild();
                }
            }
        });
    }

    private static final String SERVICE_UUID = "FFF0";
    private static final String NOTIFY_UUID = "FFF1";
    private static final String WRITE_UUID = "FFF2";


    private void openNotify() {
        mClient.notify(mDeviceMAC, Utils.makeUUID(SERVICE_UUID), Utils.makeUUID(NOTIFY_UUID), new BleNotifyResponse() {
            @Override
            public void onNotify(UUID service, UUID character, byte[] value) {
                Log.i(TAG, "onNotify: " + byteToString(value));
            }

            @Override
            public void onResponse(int code) {
                if (code == Code.REQUEST_SUCCESS) {
                    Log.i(TAG, "开启通知成功");
                } else if (code == Code.REQUEST_FAILED) {
                    Log.i(TAG, "开启通知失败");
                }
            }
        });
    }

    public void writeData(byte[] value) {
        mClient.write(mDeviceMAC, Utils.makeUUID(SERVICE_UUID), Utils.makeUUID(WRITE_UUID), value, new BleWriteResponse() {
            @Override
            public void onResponse(int code) {
                if (code == Code.REQUEST_SUCCESS) {
                    Log.i(TAG, "写入成功");
                }
            }
        });
    }

    public void disConnect() {
        mClient.refreshCache(mDeviceMAC);
        mClient.disconnect(mDeviceMAC);
    }

    public static String byteToString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();

        if (!isEmpty(bytes)) {
            for (int i = 0; i < bytes.length; i++) {
                sb.append(String.format("%02X", bytes[i]) + " ");
            }
        }

        return sb.toString();
    }
}
